def where(target, c=1, check_target = nil)
  rooms = nil
  DownstreamHook.add('where_check', Proc.new {|cs|
    if (check_target.nil? && cs.clean_colors[0..29] =~ /#{Regexp.quote(target)}/) || cs.clean_colors[0..29].strip == check_target
      full_mob = check_target || cs.clean_colors[0..30].strip
      r_name = cs.clean_colors[31..-1].strip
      rooms = $db.execute("SELECT id FROM Room WHERE name=? AND area_id=?", r_name, Area.current.db_id).flatten
      $app.add_boxes['chat'].display_text("Found '#{full_mob}' in '#{r_name}' (#{go2_string(*rooms)})\n")
      DownstreamHook.remove('where_check')
      cs.strip + " (#{go2_string(*rooms)})\n"
    else
      cs
    end
  })
  put("where #{c == 1 ? '' : "#{c}."}#{target}")
  wait_while(3) {DownstreamHook.list.include?('where_check')}
  DownstreamHook.remove('hunt_check')
  rooms
end

def where_cp(keywords, name, c)
  rooms = nil
  DownstreamHook.add('where_check', Proc.new {|cs|
    if cs.clean_colors[0..29].strip == name[0..29]
      r_name = cs.clean_colors[31..-1].strip
      rooms = $db.execute("SELECT id FROM Room WHERE name=? AND area_id=?", r_name, Area.current.db_id).flatten
      $app.add_boxes['chat'].display_text("Found '#{name}' in '#{r_name}' (#{go2_string(*rooms)})\n")
      DownstreamHook.remove('where_check')
      cs.strip + " (#{go2_string(*rooms)})\n"
    else
      cs
    end
  })
  put("where #{c == 1 ? '' : "#{c}."}#{keywords}")
  wait_while(3) {DownstreamHook.list.include?('where_check')}
  DownstreamHook.remove('where_check')
  rooms
end

def track_cp(keywords, name)
  c, found = 1, nil
  until ['hunt','area','here'].include?(found = hunt_target(keywords, c))
    (wait_until {Char.enemy.empty?};next) if found == "fighting"
    c += 1
  end
  return if found == 'area'

  if found == 'here'
    echo "Found '#{name}'!"
    put("k #{keywords}")
    return
  end
  rooms = where_cp(keywords, name, c)

  while (room = rooms.shift)
    go2(room)
    return unless Room.current.db_id == room
    mobs = get_con[0]
    mobs.each {|m|
      next unless m.gsub(/^\(.+\) /, '').casecmp(name) == 0
      echo "Found '#{name}'!"
      put("k #{keywords}")
      return
    }
  end
end

def hunt_cp(id)
  start_proc(Proc.new {
    id = id.split('-')[1].to_i - 1
    a, m, r, k = $cpi[id]['a'], $cpi[id]['m'], $cpi[id]['r'], $cpi[id]['k']
    echo "Start room unknown for area '#{a}'." if Area[a].start.nil?
    stop = false
    if ['lplanes','uplanes'].include?(a)
      plane_area = /(#{$plane_rooms.keys.join('|')})$/.match(Room[r].name)[0]
      go2($plane_rooms[plane_area])
      stop = true
    end
    if Area.current.db_id != Area[a].db_id
      if r.class == Fixnum
        go2(r)
      else
        go2(a)
      end
    end
    track_cp(k, m) unless stop
  })
end

def hunt_target(target, c=1)
  ret = nil
  DownstreamHook.add('hunt_check', Proc.new {|cs|
    if cs.clean_colors =~ /You are certain that (.+?) is (\w)|You seem unable to (hunt)|You couldn't find a (path)|No one in this (area)|is (here)!|you are (fighting)!$/
      ret = $2 || $3 || $4 || $5 || $6 || $7
      DownstreamHook.remove('hunt_check')
      cs
    elsif cs =~ /Your natural hunting skills/
      nil
    else
      cs
    end
  })
  put("hunt #{c == 1 ? '' : "#{c}."}#{target}")
  wait_while(5) {DownstreamHook.list.include?('hunt_check')}
  DownstreamHook.remove('hunt_check')
  ret
end